1 module hunt.cache.memory;
2 
3 import hunt.cache.cache;
4 import hunt.cache.store;
5 import hunt.cache.nullable;
6 
7 import core.stdc.stdlib;
8 import core.stdc.string;
9 import core.stdc.time;
10 
11 import std.variant;
12 import std.conv;
13 
14 public:
15 
16 class MemoryCache
17 {
18     Nullable!V get(V)(string key)
19     {
20         synchronized(this)
21         {
22             return get_inter!V(key);
23         }
24     }
25 
26     Nullable!V[string] getall(V)(string[] keys)
27     {
28         Nullable!V[string] mapv;
29 
30         synchronized(this)
31         {
32             foreach(k; keys)
33             {
34                 mapv[k] = get_inter!V(k);
35             }
36         }
37 
38         return mapv;
39     }
40 
41     bool containsKey(string key)
42     {
43         synchronized(this)
44         {
45             return (key in cacheData) ? true : false;
46         }
47     }
48 
49     void put(V)(string key, V v, uint expired = 0)
50     {
51         synchronized(this)
52         {
53             put_inter(key, v, expired);
54         }
55     }
56 
57     bool putifAbsent(V)(string key, V v)
58     {
59         synchronized(this)
60         {
61             bool ret = (key in cacheData) ? true : false;
62 
63             if (!ret)
64             {
65                 put_inter!V(key, v, 0);
66 
67                 return true;
68             }
69 
70             return false;
71         }
72     }
73 
74     void putAll(V)(V[string] maps, uint expired = 0)
75     {
76         synchronized(this)
77         {
78             foreach(k, v; maps)
79             {
80                 put_inter(k, v, expired);
81             }
82         }
83     }
84 
85     bool remove(string key)
86     {
87         synchronized(this)
88         {
89             if (key in cacheTime)
90             {
91                 cacheTime.remove(key);
92             }
93 
94             bool ret = (key in cacheData) ? true : false;
95 
96             if (ret)
97             {
98                 cacheData.remove(key);
99             }
100 
101             return ret;
102         }
103     }
104 
105     void removeAll(string[] keys)
106     {
107         synchronized(this)
108         {
109             foreach(k; keys)
110             {
111                 if (k in cacheTime)
112                 {
113                     cacheTime.remove(k);
114                 }
115 
116                 if (k in cacheData)
117                 {
118                     cacheData.remove(k);
119                 }
120             }
121         }
122     }
123 
124     void clear()
125     {
126         synchronized(this)
127         {
128             cacheData.clear();
129             cacheTime.clear();
130         }
131     }
132 
133     this(string args = "")
134     {
135     }
136 
137     ~this()
138     {
139         clear();
140     }
141 
142 protected:
143 
144     Variant[string] cacheData;
145     uint[string] cacheTime;
146 
147     Nullable!V get_inter(V)(string key)
148     {
149         Nullable!V v;
150 
151         if (key !in cacheTime)    //not set ttl
152         {
153             if (key in cacheData)
154             {
155                 v.bind(cacheData[key].get!V);
156             }
157 
158             return v;
159         }
160         else
161         {
162             uint tick = cacheTime[key];
163             uint now = cast(uint)time(null);
164 
165             if (tick < now) // remove
166             {
167                 cacheTime.remove(key);
168                 cacheData.remove(key);
169 
170                 return v;
171             }
172             else
173             {
174                 v.bind(cacheData[key].get!V);
175 
176                 return v;
177             }
178         }
179     }
180 
181     void put_inter(V)(string key, V v, uint expired)
182     {
183         if (expired == 0)
184         {
185             if (key in cacheTime)
186             {
187                 cacheTime.remove(key);
188             }
189         }
190         else
191         {
192             cacheTime[key] = expired + cast(uint)time(null);
193         }
194 
195         cacheData[key] = v;
196     }
197 }